home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
Modules
/
extras.em
< prev
next >
Wrap
Lisp/Scheme
|
1992-10-06
|
18KB
|
663 lines
;; Modulised .feelrc
; $Header: /denton_export/denton/You/Modules/RCS/extras.em,v 1.4 1991/01/18 20:09:01 kjp Exp $
(defmodule extras
(ccc
lists
list-operators
others
generics
classes
strings
arith
errors
(except (null) class-names)) ()
() ;Poxy, poxy...
(defun not (widget) (null widget))
(export not)
(defun caar (x) (car (car x)))
(defun cadr (x) (car (cdr x)))
(defun cdar (x) (cdr (car x)))
(defun cddr (x) (cdr (cdr x)))
(export caar cadr cdar cddr)
(defun caaar (x) (car (car (car x))))
(defun caadr (x) (car (car (cdr x))))
(defun cadar (x) (car (cdr (car x))))
(defun caddr (x) (car (cdr (cdr x))))
(defun cdaar (x) (cdr (car (car x))))
(defun cdadr (x) (cdr (car (cdr x))))
(defun cddar (x) (cdr (cdr (car x))))
(defun cdddr (x) (cdr (cdr (cdr x))))
(export caaar caadr cadar caddr cdaar cdadr cddar cdddr)
(defun caaaar (x) (car (car (car (car x)))) )
(defun caaadr (x) (car (car (car (cdr x)))) )
(defun caadar (x) (car (car (cdr (car x)))) )
(defun caaddr (x) (car (car (cdr (cdr x)))) )
(defun cadaar (x) (car (cdr (car (car x)))) )
(defun cadadr (x) (car (cdr (car (cdr x)))) )
(defun caddar (x) (car (cdr (cdr (car x)))) )
(defun cadddr (x) (car (cdr (cdr (cdr x)))) )
(defun cdaaar (x) (cdr (car (car (car x)))) )
(defun cdaadr (x) (cdr (car (car (cdr x)))) )
(defun cdadar (x) (cdr (car (cdr (car x)))) )
(defun cdaddr (x) (cdr (car (cdr (cdr x)))) )
(defun cddaar (x) (cdr (cdr (car (car x)))) )
(defun cddadr (x) (cdr (cdr (car (cdr x)))) )
(defun cdddar (x) (cdr (cdr (cdr (car x)))) )
(defun cddddr (x) (cdr (cdr (cdr (cdr x)))) )
(export caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr cdaaar
cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr)
(defun neq (a b) (not (equal a b)))
(defun geq (a b) (null (lessp a b)))
(defun leq (a b) (null (greaterp a b)))
(defun eqcar (a b) (cond ((atom a) nil) ((eq (car a) b) t) (t nil)))
(export neq geq leq eqcar)
(defun mkquote (x) (list 'quote x))
(export mkquote)
(defun assq (a l)
(cond
((null l) nil)
((eq a (caar l)) (car l))
(t (assq a (cdr l)))) )
(export assq)
(defun list-ref (list n)
(if (equal n 0) (car list)
(list-ref (cdr list) (\- n 1))))
(defun \@list-ref-update\@ (list n obj)
(if (equal n 0) ((setter car) list obj)
(list-ref (cdr list) (\- n 1))))
((setter setter) list-ref \@list-ref-update\@)
(export list-ref)
(defun reverse (l)
(labels ((rev1 (l n)
(if (null l) n
(rev1 (cdr l) (cons (car l) n)))))
(rev1 l nil)))
(export reverse)
(defun subst (a b c)
(cond
((equal c b) a)
((atom c) c)
(t
((lambda (carc cdrc)
(cond ((and (eq carc (car c)) (eq cdrc (cdr c))) c)
(t (cons carc cdrc))))
(subst a b (car c))
(subst a b (cdr c))))))
(defun delete (a b comp)
(cond
((null b) nil)
((comp a (car b)) (cdr b))
(t ((lambda (del)
(cond ((eq del (cdr b)) b)
(t (cons (car b) del))))
(delete a (cdr b) comp)))))
(defun deleteq (a b)
(cond
((null b) nil)
((eq a (car b)) (cdr b))
(t ((lambda (del)
(cond ((eq del (cdr b)) b)
(t (cons (car b) del))))
(deleteq a (cdr b))))))
(export subst delete deleteq)
;; This definition does not allow for arbitary numbers of args
(defun mapcan (*fn* . x)
(let ((len (list-length x)))
(cond ((= len 1) (mapcan1 *fn* (car x)))
((= len 2) (mapcan2 *fn* (car x) (cadr x)))
((= len 3) (mapcan3 *fn* (car x) (cadr x) (caddr x)))
(t (error 0 "mapcan unfinished")))))
(defun mapcan1 (*fn* x)
(if (null x) nil
(nconc (*fn* (car x)) (mapcan1 *fn* (cdr x)))))
(defun mapcan2 (*fn* x y)
(if (or (null x) (null y)) nil
(nconc (*fn* (car x) (car y)) (mapcan2 *fn* (cdr x) (cdr y)))))
(defun mapcan3 (*fn* x y z)
(if (or (null x) (null y) (null z)) nil
(nconc (*fn* (car x) (car y) (car z))
(mapcan3 *fn* (cdr x) (cdr y) (cdr z)))))
;; This definition does not allow for arbitary numbers of args
(defun mapcon (*fn* . x)
(let ((len (list-length x)))
(cond ((= len 1) (mapcon1 *fn* (car x)))
((= len 2) (mapcon2 *fn* (car x) (cadr x)))
((= len 3) (mapcon3 *fn* (car x) (cadr x) (caddr x)))
(t (error 0 "mapcon unfinished")))))
(defun mapcon1 (*fn* x)
(if (null x) nil
(nconc (*fn* x) (mapcon1 *fn* (cdr x)))))
(defun mapcon2 (*fn* x y)
(if (null x) nil
(nconc (*fn* x y) (mapcon1 *fn* (cdr x) (cdr y)))))
(defun mapcon3 (*fn* x y z)
(if (null x) nil
(nconc (*fn* x y z) (mapcon3 *fn* (cdr x) (cdr y) (cdr z)))))
(export mapcan mapcon)
(defun maplist (*fn* l)
(prog (ans)
top (cond ((null l) (return (nreverse ans))))
(setq ans (cons (*fn* l) ans))
(setq l (cdr l))
(go top)))
(export maplist)
;; Control Extentions - Binding extentions
;; LET expands to LAMBDA
(defmacro let (bind . body)
(cons (cons 'lambda (cons (\@letvars bind) body)) (\@letforms bind)))
(defun \@letvars (b)
(if b (cons (car (car b)) (\@letvars (cdr b)))
nil))
(defun \@letforms (b)
(if b (cons (car (cdr (car b))) (\@letforms (cdr b)))
nil))
;; LET* expands to LET
(defmacro let* (bind . body)
(if bind (list 'let (cons (car bind) nil)
(cons 'let* (cons (cdr bind) body)))
(cons 'progn body)))
;; LABELS is a complex LET
(defmacro labels (binds . body)
(cons 'let (cons (\@labelsvar binds) (\@labelsbody binds body))))
(defun \@labelsvar (b)
(if b (cons (list (car (car b)) nil) (\@labelsvar (cdr b)))
nil))
(defun \@labelsbody (b body)
(if b (cons (list 'setq (car (car b)) (cons 'lambda (cdr (car b))))
(\@labelsbody (cdr b) body))
body))
(export let let* labels)
;; Control Extentions - Conditional Extentions
(defmacro cond b
(if b (if (cdr (car b)) (list 'if (car (car b)) (cons 'progn (cdr (car b)))
(cons 'cond (cdr b)))
(list 'or (car (car b)) (cons 'cond (cdr b))))
nil))
(defmacro and b
(if b (if (cdr b) (list 'if (car b) (cons 'and (cdr b)) nil)
(car b))
t))
(defmacro or b
(if b
(if (cdr b) (list 'let (list (list '\@ (car b)))
(list 'if '\@ '\@ (cons 'or (cdr b))))
(car b))
nil))
(export cond and or)
;; Control Extentions - Exit Extentions
(defmacro block forms (cons 'let/cc forms))
(defmacro return-from (name . forms)
(list name (cons 'progn forms)))
(defmacro catch (tag . body)
`(let/cc \@
(dynamic-let ((,tag \@)) ,@body)))
(defmacro throw (tag . forms)
`((dynamic ,tag) (progn ,@forms)))
(export block return-from catch throw)
;;(defmacro with-(dummy handler-fn . forms)
;; `(let/cc accept
;; (let ((decline (current-handler)))
;; ((setter current-handler)
;; (lambda (condition cont)
;; (,handler-fn condition cont)
;; ;; Returned => next handler...
;; ((setter current-handler) decline)
;; (decline condition cont)))
;; (unwind-protect
;; (progn (unquote-splicing forms))
;; ((setter current-handler) decline)))))
;; This is from Christian, and I think that it is not quite right
;;(defun add-handler (old-handler function)
;; (let ((condition) (a) (c))
;; (let/cc decline
;; (function condition a
;; (lambda () (old-handler condition a decline c))
;; c))))
;; (export with-handler add-handler)
(defmacro go (a) `(return (,a)))
(defmacro return a `(return-from label-block ,@a))
;;(defun \@anylabelsp (forms)
;; (if (null forms) nil
;; (if (symbolp (car forms)) t
;; (\@anylabelsp (cdr forms)))))
;;(defun \@firstlabel (forms)
;; (if (null forms) nil
;; (if (symbolp (car forms)) (cons (cons (car forms) nil) nil)
;; (cons (car forms) (\@firstlabel (cdr forms))))))
;;(defun \@getseqs (forms)
;; (if (null forms) nil
;; (if (null (symbolp (car forms))) (\@getseqs (cdr forms))
;; (cons (cons (cons (car forms)
;; (cons nil (\@firstlabel (cdr forms)))) nil)
;; (\@getseqs (cdr forms))))))
;;(defmacro tagbody (dummy . forms)
;; (if (null (\@anylabelsp forms))
;; `(block label-block ,@forms)
;; (cons 'block (list 'label-block
;; (cons 'labels
;; (append (\@getseqs forms)
;; (\@firstlabel forms)))))))
(defun tagbody-til-label (forms)
(cond ((null forms) nil)
((symbolp (car forms)) (tagbody-til-label (cdr forms)))
(t (cons (car forms) (tagbody-til-label (cdr forms))))))
(defun real-tagbody-til-label (forms)
(cond ((null forms) nil)
((symbolp (car forms)) nil)
(t (cons (car forms) (real-tagbody-til-label (cdr forms))))))
(defun tagbody-label-forms (forms)
(cond ((null forms) nil)
((symbolp (car forms))
(cons
(cons (car forms) (cons () (tagbody-til-label (cdr forms))))
(tagbody-label-forms (cdr forms))))
(t (tagbody-label-forms (cdr forms)))))
(defun tagbody-first-label (forms)
(cond ((null forms) nil)
((symbolp (car forms)) (car forms))
(t (tagbody-first-label (cdr forms)))))
(defmacro tagbody forms
(let ((post (tagbody-label-forms forms))
(lab1 (tagbody-first-label forms)))
(if (null post) ;; No labels
`(block label-block ,@forms)
`(block label-block
,@(real-tagbody-til-label forms) ;; Before any labels
(labels ,post
,(list lab1)))))) ;; Jump to first label
;; (export go return tagbody)
(export return)
(defmacro prog1 forms
`((lambda (@prog1-handle@)
,@(cdr forms)
@prog1-handle@) ,(car forms)))
(export prog1)
;; Quasi-quoting
;;(defmacro quasiquote (dummy form)
;; (labels ((\@unquote-constructor (x)
;; (cond ((atom x)
;; (cond ((or (null x) (numberp x) (stringp x) (eq x t)) x)
;; (t (mkquote x))))
;;
;; ((eq (car x) 'unquote) (cadr x))
;; ((eq (car x) 'unquote-spicing)
;; (error 0 "Illegal use of ,@ marker"))
;; ((eqcar (car x) 'unquote-splicing)
;; (list 'append (cadar x) (\@unquote-constructor (cdr x))))
;; ;; ((\@contains-no-unquote x) (mkquote x))
;; (t (list 'cons
;; (\@unquote-constructor (car x))
;; (\@unquote-constructor (cdr x))))))
;; (\@contains-no-unquote (x)
;; (cond ((atom x) t)
;; ((or (eq (car x) 'unquote) (eq (car x) 'unquote-splicing))
;; nil)
;; (t (and (\@contains-no-unquote (car x))
;; (\@contains-no-unquote (cdr x)))))))
;; (\@unquote-constructor form)))
;; Having realised the embarrasing overhead of local functions in
;; the interpretter...
;; Quasi-quoting
(defun \@unquote-constructor (x)
(cond ((atom x)
(cond ((or (null x) (numberp x) (stringp x) (eq x t)) x)
(t (mkquote x))))
((eq (car x) 'unquote) (cadr x))
((eq (car x) 'unquote-spicing)
(error 0 "Illegal use of ,@ marker"))
((eqcar (car x) 'unquote-splicing)
(list 'append (cadar x) (\@unquote-constructor (cdr x))))
;; ((\@contains-no-unquote x) (mkquote x))
(t (list 'cons
(\@unquote-constructor (car x))
(\@unquote-constructor (cdr x))))))
(defun \@contains-no-unquote (x)
(cond ((atom x) t)
((or (eq (car x) 'unquote) (eq (car x) 'unquote-splicing))
nil)
(t (and (\@contains-no-unquote (car x))
(\@contains-no-unquote (cdr x))))))
;; (defmacro quasiquote (dummy form) (\@unquote-constructor form))
(export quasiquote)
;; Multiple-value-bind and multiple-value-setq from Jeff Dalton, but wrong
(defmacro multiple-bind (dummy vars multiple-value-form . body)
`(multiple-value-call (lambda ,vars (unquote-splicing body))
,multiple-value-form))
(defmacro multiple-setq (dummy vars multiple-value-form)
;; get one temp var gensym for each variable
(let ((temps (mapcar (lambda (v) (gensym))
vars)))
;; put the multiple values in the temp vars
`(multiple-value-bind ,temps ,multiple-value-form
;; assign the value of each temp var to the corresponding
;; variable
(unquote-splicing (mapcar (lambda (v g) `(setq ,v ,g))
vars
temps)))))
;;;;
;;(deflocal foo1
;; (macroexpand
;; '(with-handler (lambda (c a d) (print c))
;; (signal (make-condition 'bar 123)))))
;;(deflocal foo2
;; (macroexpand
;; '(with-handler (lambda (c a d) (print c) (a 456))
;; (signal (make-condition 'bar 123)))))
;;(deflocal foo3
;; (macroexpand
;; '(with-handler (lambda (c a d) (print c) (d c))
;; (signal (make-condition 'bar 123)))))
;;;;
;; Noddy evaluator for a file of lisp forms
(defun rdf(path)
(rdf-read-form (open path 'input)))
(defun rdf-read-form(instream)
(let ((form (read instream)))
(cond ((end-of-stream-p form) (close instream) t)
(t (eval/cm form) (rdf-read-form instream)))))
(export rdf)
(defmacro prog (vars . body)
`(block label-block
((lambda ,vars (tagbody ,@body)) ,@(mapcar (lambda (a) nil) vars))
nil))
(export prog)
(defmacro when (pred . forms) `(if ,pred (progn ,@forms) nil))
(defmacro unless (pred . forms) `(if ,pred nil (progn ,@forms)))
(export when unless)
;;
;; Missing bits...
;;
(defgeneric positivep (i))
(export positivep)
(defmethod positivep ((i number)) (< i 0))
(defgeneric negativep (i))
(export negativep)
(defmethod negativep ((i number)) (< i 0))
(defgeneric negate (x))
(export negate)
(defmethod negate ((x number)) (- x))
(defun make-polar (r theta)
(make-rectangular (* r (cos theta)) (* r (sin theta))))
(export make-polar)
(defun argument (x) (atan2 (imaginary-part x) (real-part x)))
(export argument)
(defun modulus (x)
(let ((rr (real-part x))
(ii (imaginary-part x)))
(exp (* 0.5 (log (+ (* rr rr) (* ii ii)))))))
(export modulus)
(defun list-copy-aux (l new)
(if l (list-copy-aux (cdr l) (nconc new (cons (car l) nil)))
new))
(defun list-copy (l) (list-copy-aux l nil))
(export list-copy)
(defun copy-alist (lst)
(if (null lst) nil
(cons (cons (caar lst) (cdar lst)) (copy-alist (cdr lst)))))
(export copy-alist)
(defun list-tail (lst n) (list-tail-aux lst (- (list-length lst) n)))
(defun list-tail-aux (lst n)
(if (> n 0) (list-tail-aux (cdr lst) (- n 1)) lst))
(export list-tail)
(defun posq (obj lst) (posq-aux obj lst 1))
(defun posq-aux (obj lst n)
(if (null lst) -1
(if (eq obj (car lst)) n (posq-aux obj (cdr lst) (+ n 1)))))
(export posq)
(defun pos (obj lst) (pos-aux obj lst 1))
(defun pos-aux (obj lst n)
(if (null lst) -1
(if (equal obj (car lst)) n (pos-aux obj (cdr lst) (+ n 1)))))
(export pos)
(defgeneric binary-max (a b))
(export binary-max)
(defmethod binary-max ((a number) (b number)) (max a b))
(defgeneric binary-min (a b))
(export binary-min)
(defmethod binary-min ((a number) (b number)) (min a b))
(defun string-slice (str start end)
(let ((n (- (+ end 1) start)))
(string-slice-aux (make-string n) str 0 start end)))
(defun string-slice-aux (new old n start end)
(if (> start end) new
(progn ((setter string-ref) new n (string-ref old start))
(string-slice-aux new old (+ n 1) (+ start 1) end))))
(export string-slice)
; some easy convert methods
(defmethod generic-convert ((x real) (n integer)) (floor x))
(defmethod generic-convert ((n integer) (x real)) (+ n 0.0))
; a simple definition for expt.
(defgeneric expt (x n))
(export expt)
(defcondition expt-error ())
(defun raise (mess val)
(signal (make-condition expt-error
'message mess
'error-value val)
()))
(defmethod expt ((x object) (n object))
(signal (raise "not a real in expt" x) ()))
(defmethod expt ((x real) (n object))
(signal (raise "not an integer in expt" n) ()))
(defmethod expt ((x object) (n integer))
(signal (raise "not a real in expt" x) ()))
; probably (expt 2 -1) should be rational 1/2, but we don't have
; complete support for that at the moment
(defmethod expt ((x integer) (n integer))
(cond ((= x 0)
(cond ((< n 0) (raise "inverse of 0 in expt" 0))
((= n 0) (raise "0^0 in expt" 0))
(t 0)))
((< n 0)
(/ 1.0 (expt-real (convert x real) (- n))))
((= n 0) 1)
(t (expt-int x n))))
(defmethod expt ((x rational) (n integer))
(signal (raise "unimplemented rational arithmetic in expt" x) ()))
(defmethod expt ((x real) (n integer))
(cond ((= x 0.0)
(cond ((< n 0) (raise "inverse of 0.0 in expt" 0))
((= n 0) (raise "0.0^0 in expt" 0.0))
(t 0.0)))
((< n 0)
(/ 1.0 (expt-real x (- n))))
((= n 0) 1.0)
(t (expt-real x n))))
; n a positive integer
; x a positive integer
(defun expt-int (x n)
(cond ((zerop n) 1)
((= n 1) x)
(t (let ((xx (expt-int x (/ n 2))))
(if (evenp n)
(* xx xx)
(* xx xx x))))))
; x a non-zero real
(defun expt-real (x n)
(if (< x 0.0)
(if (evenp n)
(expt-pos-real (- x) n)
(- (expt-pos-real (- x) n)))
(expt-pos-real x n)))
; x a positive real
(defun expt-pos-real (x n)
(exp (* n (log x))))
(defgeneric generic-open (path . options))
(export generic-open)
(defmethod generic-open ((a string) . opt) (apply open a opt))
(defgeneric make-io-stream (instream outstream))
(export make-io-stream)
(defgeneric generic-read-char (stream))
(export generic-read-char)
(defgeneric generic-read-byte (stream))
(export generic-read-byte)
(defgeneric generic-peek-char (stream))
(export generic-peek-char)
(defgeneric generic-peek-byte (stream))
(export generic-peek-byte)
(defgeneric generic-write-char (ch str))
(export generic-write-char)
(defgeneric generic-write-byte (n str))
(export generic-write-byte)
(defgeneric generic-log (x))
(export generic-log)
(defmethod generic-log ((a number)) (log a))
(defmethod generic-log ((a complex))
(make-rectangular (log (modulus a)) (argument a)))
(defun functionp (obj) (subclassp (class-of obj) function))
(export functionp)
)